--- /dev/null
- env: "compile",
+use std::io::process::ExitStatus;
+use docopt;
+
+use cargo::ops;
+use cargo::core::{MultiShell};
+use cargo::util::{CliResult, CliError};
+use cargo::util::important_paths::{find_root_manifest_for_cwd};
+
+docopt!(Options, "
+Run the main binary of the local package (src/main.rs)
+
+Usage:
+ cargo run [options] [--] [<args>...]
+
+Options:
+ -h, --help Print this message
+ -j N, --jobs N The number of jobs to run in parallel
++ --release Build artifacts in release mode, with optimizations
++ --target TRIPLE Build for the target triple
+ -u, --update-remotes Deprecated option, use `cargo update` instead
+ --manifest-path PATH Path to the manifest to execute
+ -v, --verbose Use verbose output
+
+All of the trailing arguments are passed as to the binary to run.
+", flag_jobs: Option<uint>, flag_target: Option<String>,
+ flag_manifest_path: Option<String>)
+
+pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
+ shell.set_verbose(options.flag_verbose);
+ let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
+
+ let mut compile_opts = ops::CompileOptions {
+ update: options.flag_update_remotes,
- target: None,
++ env: if options.flag_release { "release" } else { "compile" },
+ shell: shell,
+ jobs: options.flag_jobs,
++ target: options.flag_target.as_ref().map(|t| t.as_slice()),
+ dev_deps: true,
+ };
+
+ let err = try!(ops::run(&root, &mut compile_opts,
+ options.arg_args.as_slice()).map_err(|err| {
+ CliError::from_boxed(err, 101)
+ }));
+ match err {
+ None => Ok(None),
+ Some(err) => {
+ Err(match err.exit {
+ Some(ExitStatus(i)) => CliError::from_boxed(box err, i as uint),
+ _ => CliError::from_boxed(box err, 101),
+ })
+ }
+ }
+}
+
let mut src = try!(PathSource::for_path(&manifest_path.dir_path()));
try!(src.update());
let root = try!(src.get_root_package());
+ let mut bins = root.get_manifest().get_targets().iter().filter(|a| {
+ a.is_bin() && a.get_profile().is_compile()
+ });
+ let bin = try!(bins.next().require(|| {
+ human("a bin target must be available for `cargo run`")
+ }));
+ match bins.next() {
+ Some(..) => return Err(human("`cargo run` requires that a project only \
+ have one executable")),
+ None => {}
+ }
let compile = try!(ops::compile(manifest_path, options));
- let exe = manifest_path.dir_path().join("target").join(bin.get_name());
+ let mut exe = manifest_path.dir_path().join("target");
+ if options.env == "release" {
+ exe = exe.join("release");
+ }
- let exe = exe.join(root.get_name());
++ let exe = exe.join(bin.get_name());
let exe = match exe.path_relative_from(&os::getcwd()) {
Some(path) => path,
None => exe,
execs().with_status(0));
})
+ test!(release_works {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/main.rs", r#"
+ fn main() { if !cfg!(ndebug) { fail!() } }
+ "#);
+
+ assert_that(p.cargo_process("cargo-run").arg("--release"),
+ execs().with_status(0).with_stdout(format!("\
+ {compiling} foo v0.0.1 ({dir})
+ {running} `target{sep}release{sep}foo`
+ ",
+ compiling = COMPILING,
+ running = RUNNING,
+ dir = path2url(p.root()),
+ sep = path::SEP).as_slice()));
+ assert_that(&p.release_bin("foo"), existing_file());
+ })
++
+test!(run_bin_different_name {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "bar"
+ "#)
+ .file("src/bar.rs", r#"
+ fn main() { }
+ "#);
+
+ assert_that(p.cargo_process("run"), execs().with_status(0));
+})